/*
 * Copyright 2011 Oracle Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **/

package org.sunspotworld.demo;

import com.sun.spot.core.resources.Resources;
import com.sun.spot.core.resources.transducers.IToneGenerator;
import com.sun.spot.core.util.Utils;

/**
 * We use the song "Jingle Bells" (http://en.wikipedia.org/wiki/Jingle_Bells).
 *
 * @author vgupta
 */
public class Melody {
    public static final int WHOLE_NOTE_TIME = 800; // in milli seconds
    public static final int GAP_BETWEEN_NOTES = WHOLE_NOTE_TIME/32;
    public static final int NN = 0; // "no note" indicates rest

    // This song uses only nine notes and here are their
    // frequencies (rounded to the nearest integer). See
    // http://www.phy.mtu.edu/~suits/notefreqs.html
    // for a complete mapping of music notes to frequencies.

    public static final int D4 = 294;
    public static final int E4 = 330;
    public static final int F4 = 349;
    public static final int G4 = 392;
    public static final int A4 = 440;
    public static final int B4 = 494;
    public static final int C5 = 523;
    public static final int D5 = 587;
    public static final int E5 = 659;

    // The sheet music for this song (see
    // http://www.1manband.nl/sheetmusic/jingle%20bells.jpg) has
    // eight staff lines. Each has either four or five measures (bars).
    // We try to preserve as much of the sheet music structure as possible
    // in our encoding below. Spaces between clusters of notes indicate bars.
    private int[] notes = {
              D4,        D4,B4,A4,G4,     D4,NN,D4,     D4,B4,A4,G4,                 
        E4,NN,E4,        E4,C5,B4,A4,     F4,NN,D5,     D5,D5,C5,A4,                 
        B4,G4,D4,        D4,B4,A4,G4,     D4,NN,D4,     D4,B4,A4,G4,                 
        E4,NN,E4,        E4,C5,B4,A4,     D5,D5,D5,D5,  E5,D5,C5,A4,                 
        G4,NN,           B4,B4,B4,        B4,B4,B4,     B4,D5,G4,A4,   B4,NN,        
        C5,C5,C5,C5,     C5,B4,B4,B4,B4,  B4,A4,A4,B4,  A4,D5,                       
        B4,B4,B4,        B4,B4,B4,        B4,D5,G4,A4,  B4,NN,         C5,C5,C5,C5,
        C5,B4,B4,B4,B4,  D5,D5,C5,A4,     G4
    };

    // The smallest duration for a note in this song is 1/8th of the measure
    // so we express the durations as multiples of 1/8th, i.e. a "quarter-note"
    // (these look like p or d in the sheet music with the hollow part filled
    // in) is represented as 2, a "half-note" (these look like p or d) as 4.
    // A dot following a note extends its duration by 50%.
    private int[] durations = {
                2,       2,2,2,2,          4,2,2,       2,2,2,2,
            4,2,2,       2,2,2,2,          4,2,2,       2,2,2,2,
            4,2,2,       2,2,2,2,          4,2,2,       2,2,2,2,
            4,4,4,       2,2,2,2,          2,2,2,2,     2,2,2,2,
            6,2,         2,2,4,            2,2,4,       2,2,3,1,       6,2,
            2,2,3,1,     2,2,2,1,1,        2,2,2,2,     4,4,
            2,2,4,       2,2,4,            2,2,3,1,     6,2,           2,2,3,1,
            2,2,2,1,1,   2,2,2,2,          6
    };

    

    public void playOnce() {
        IToneGenerator tg = (IToneGenerator) Resources.lookup(IToneGenerator.class);

        // Start of song ...
        Utils.sleep(2*WHOLE_NOTE_TIME);
        System.out.println("Playing melody ...");
        
        for (int i = 0; i < notes.length; i++) {
            if (notes[i] == NN) {
                Utils.sleep(durations[i] * WHOLE_NOTE_TIME / 8);
            } else {
                tg.startTone(notes[i]);
                Utils.sleep(durations[i] * WHOLE_NOTE_TIME / 8);
                tg.stopTone();
            }
            
            Utils.sleep(GAP_BETWEEN_NOTES);
        }
    }
}